/*
 * Copyright 2010 Christoph Widulle (christoph.widulle@googlemail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */


package com.android1.amarena2d.input;

import com.android1.amarena2d.engine.EngineObject;
import com.android1.amarena2d.engine.Timer;


public abstract class LongPressDetector implements TouchListener {

    public static final float DEFAULT_DELAY = 0.8F;

    private float delay = DEFAULT_DELAY;
    private boolean exclusive;

    private final TimerImpl timer = new TimerImpl(this);

    float lastX, lastY;
    int activePointer = -1;

    public LongPressDetector() {
    }

    public LongPressDetector(float delay) {
        this.delay = delay;
    }

    public boolean isExclusive() {
        return exclusive;
    }

    /**
     * If true, will consume the event and no other touchlistener will be notified.
     *
     * @param exclusive
     * @return
     */
    public LongPressDetector setExclusive(final boolean exclusive) {
        this.exclusive = exclusive;
        return this;
    }

    public abstract void onLongPress(float x, float y, int pointer);

    @Override
    public boolean onTouchDown(float x, float y, int pointer, boolean isHit) {
        if ((this.activePointer != -1 && this.activePointer != pointer))
            return false;
        this.activePointer = pointer;
        this.lastX = x;
        this.lastY = y;
        timer.start();
        return exclusive;
    }

    @Override
    public boolean onTouchUp(float x, float y, int pointer, boolean isHit) {
        if ((this.activePointer != -1 && this.activePointer != pointer))
            return false;
        this.activePointer = -1;
        this.lastX = x;
        this.lastY = y;
        timer.stop();
        return exclusive;
    }

    @Override
    public boolean onTouchDragged(float x, float y, int pointer, boolean isHit) {
        if ((this.activePointer != -1 && this.activePointer != pointer))
            return false;
        this.lastX = x;
        this.lastY = y;
        return exclusive;
    }

    /**
     * Stops the current running long press detection timer.
     */
    public void cancel() {
        timer.stop();
    }


    public static final class TimerImpl extends EngineObject implements Timer {

        LongPressDetector owner;
        float elapsed;
        float delay;
        boolean active;

        private TimerImpl(LongPressDetector owner) {
            this.owner = owner;
        }

        public void start() {
            this.delay = owner.delay;
            this.elapsed = 0;
            if (!active)
                engine.getScheduler().schedule(this);
            active = true;
            engine.log("LongPressTimer", "Start");
        }

        public void stop() {
            if (active)
                engine.getScheduler().unschedule(this);
            active = false;
            engine.log("LongPressTimer", "Stop");
        }

        @Override
        public void tick(float d) {
            elapsed += d;
            if (elapsed > delay) {
                stop();
                owner.onLongPress(owner.lastX, owner.lastY, owner.activePointer);
            }
        }


        @Override
        public boolean isPaused() {
            return false;
        }

        @Override
        public void resume() {

        }

        @Override
        public void pause() {

        }

        @Override
        public void setRecycleable(boolean recycleable) {

        }

        @Override
        public boolean isFinished() {
            return false;
        }

        @Override
        public boolean isRecyclable() {
            return false;
        }

        @Override
        public void recycle() {

        }
    }
}